/*
 * Created on Aug 21, 2005
 *
 */
package org.mushroomdb.engine.operation.impl;

import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.TreeMap;

import org.mushroomdb.catalog.Column;
import org.mushroomdb.catalog.Register;
import org.mushroomdb.engine.operation.AbstractUnaryRelationOperation;
import org.mushroomdb.engine.operation.RelationOperation;
import org.mushroomdb.engine.optimizer.RelationOperationVisitor;
import org.mushroomdb.executionplan.ExecutionPlanElement;
import org.mushroomdb.executionplan.ExecutionPlanElementImpl;
import org.mushroomdb.util.comparator.ReverseComparator;


/**
 * @author Matu
 *
 */
public class TreeMapSortOperation extends AbstractUnaryRelationOperation {
	private Column column;
	private boolean asc;

	/**
	 * @param relationOperation
	 */
	public TreeMapSortOperation(RelationOperation relationOperation, Column column, boolean asc) {
		super(relationOperation);
		this.column = column;
		this.asc = asc;
	}

	/**
	 * @see org.mushroomdb.engine.operation.RelationOperation#execute()
	 */
	public Iterator execute() {
		
		return new Iterator() {
			private TreeMap registers;
			private Iterator keys;
			
			public void remove() {
				throw new UnsupportedOperationException();
			}

			public boolean hasNext() {
				if (keys == null) {
					this.loadRegisters();
				}
				return keys.hasNext();
			}

			public Object next() {
				if (keys == null) {
					this.loadRegisters();
				}
				Object key = keys.next();
				return this.registers.get(key);
			}
			
			private void loadRegisters() {
				/** Construye el mapa para ASC o DESC */
				if (TreeMapSortOperation.this.asc) {
					this.registers = new TreeMap();
				} else {
					this.registers = new TreeMap(new ReverseComparator());
				}
				
				Iterator iterator = TreeMapSortOperation.this.relationOperation.execute();
				while (iterator.hasNext()) {
					Register register = (Register) iterator.next();
					int index = register.getColumnIndex(TreeMapSortOperation.this.column);
					Comparable key = (Comparable) register.getValue(index);
					this.registers.put(key,register);
				}
				this.keys = this.registers.keySet().iterator();
			}
		};
	}

	/**
	 * @see org.mushroomdb.engine.operation.RelationOperation#buildExecutionPlan()
	 */
	public ExecutionPlanElement buildExecutionPlan() {
		List attributes = new LinkedList();
		attributes.add(this.column.getName());
		
		ExecutionPlanElementImpl executionPlanElement =
			new ExecutionPlanElementImpl("ORDER:" + (this.asc ? "ASC" : "DESC"),attributes);   //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$
		executionPlanElement.addChild(this.relationOperation.buildExecutionPlan());
		
		return executionPlanElement;
	}

	/**
	 * toString
	 */
	public String toString() {
		return "ORDER:" + (this.asc ? "ASC" : "DESC") +   //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$
			"[" + this.column.getName() + "]("  //$NON-NLS-1$//$NON-NLS-2$
			+ this.relationOperation.toString() + ")"; //$NON-NLS-1$
	}
	
	/**
	 * @see org.mushroomdb.engine.operation.RelationOperation#accept(com.mdlm.rdbms.engine.optimizer.RelationOperationVisitor)
	 */
	public void accept(RelationOperationVisitor v) {
	}

}
